package com.yjzx.util.binlog.core.entiry;

import com.github.shyiko.mysql.binlog.event.EventHeader;
import com.github.shyiko.mysql.binlog.event.EventType;
import lombok.Getter;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yjzx
 * @date 2024/7/6
 * @description
 */
@Getter
public class BinLogDml extends BinLog {
    /**
     * 存储字段-之后的值(保存 更新)
     */
    private Map<String, Serializable> after = null;
    /**
     * 存储字段-之前的值(删除 更新)
     */
    private Map<String, Serializable> before = null;

    // 存储字段--类型
    private final ColumData[] colums;

    public BinLogDml(String database, String table, EventType eventType, long timestamp, long serverId, ColumData[] colums) {
        super(database, table, eventType, timestamp, serverId);
        this.colums = colums;
    }

    /**
     * 新增或者删除操作数据格式化
     */
    public static BinLogDml itemFrom(String database, String table, Serializable[] row, ColumData[] columMap, EventType eventType, EventHeader header) {
        if (null == row || null == columMap) {
            return null;
        }
        if (row.length != columMap.length) {
            return null;
        }
        // 初始化Item
        BinLogDml item = new BinLogDml(database, table, eventType, header.getTimestamp(), header.getServerId(), columMap);

        item.toData(row);
        return item;
    }


    /**
     * 更新操作数据格式化
     */
    public static BinLogDml itemFrom(String database, String table, Map.Entry<Serializable[], Serializable[]> mapEntry, ColumData[] colums, EventType eventType, EventHeader header) {
        if (null == mapEntry || null == colums) {
            return null;
        }
        // 初始化Item
        BinLogDml item = new BinLogDml(database, table, eventType, header.getTimestamp(), header.getServerId(), colums);
        item.toData(mapEntry);
        return item;
    }

    private void toData(Serializable[] row) {
        Map<String, Serializable> beOrAf = new HashMap<>(16);
        for (ColumData colum : colums) {
            beOrAf.put(colum.colName, row[colum.inx]);
        }
        ;
        // 写操作放after
        if (isWrite()) {
            this.after = beOrAf;
        }
        // 删操作放before
        if (isDelete()) {
            before = beOrAf;
        }
    }

    private void toData(Map.Entry<Serializable[], Serializable[]> mapEntry) {
        Map<String, Serializable> be = new HashMap<>(16);
        Map<String, Serializable> af = new HashMap<>(16);
        for (ColumData colum : colums) {
            be.put(colum.colName, mapEntry.getKey()[colum.inx]);
            af.put(colum.colName, mapEntry.getValue()[colum.inx]);
        }
        this.before = be;
        this.after = af;
    }

    public boolean isWrite() {
        return eventType == EventType.PRE_GA_WRITE_ROWS || eventType == EventType.WRITE_ROWS || eventType == EventType.EXT_WRITE_ROWS;
    }

    public boolean isUpdate() {
        return eventType == EventType.PRE_GA_UPDATE_ROWS || eventType == EventType.UPDATE_ROWS || eventType == EventType.EXT_UPDATE_ROWS;
    }

    public boolean isDelete() {
        return eventType == EventType.PRE_GA_DELETE_ROWS || eventType == EventType.DELETE_ROWS || eventType == EventType.EXT_DELETE_ROWS;
    }

    @Override
    public String toString() {
        return "BinLogItem{" +
                "dataBase=" + database +
                ", table=" + table +
                ", eventType=" + (isDelete() ? "删除" : isUpdate() ? "更新" : isWrite() ? "新增" : "未知") +
                ", timestamp=" + timestamp +
                ", serverId=" + serverId +
                ", after=" + after +
                ", before=" + before +
                ", colums=" + colums +
                '}';
    }
}
